#include <stdio.h>
#include <string.h>
#include <signal.h>
#include <unistd.h>
#include <wait.h>
#include <sys/types.h>
#include <stdlib.h>

// 定义信号处理函数，当接收到 SIGCHLD 信号时会调用此函数
// sig 是接收到的信号编号
void sigchld_handler(int sig)
{
    // 用于存储子进程的退出状态
    int status;
    // 等待任意一个子进程结束，并将其退出状态存储到 status 中
    // -1 表示等待任意子进程，0 表示不使用额外选项
    waitpid(-1, &status, 0);
    // 判断子进程是否正常退出（通过 return 或 exit 函数）
    if (WIFEXITED(status))
        printf("child process exit normally\n");
    // 判断子进程是否因信号而异常退出
    else if (WIFSIGNALED(status))
        printf("child process exit abnormally\n");
    // 判断子进程是否被暂停
    else if (WIFSTOPPED(status))
        printf("child process is stopped\n");
    // 如果以上条件都不满足，则输出 else
    else
        printf("else");
}

int main()
{
    // 定义一个进程 ID 类型的变量，用于存储 fork 函数的返回值
    pid_t pid;
    // 为 SIGCHLD 信号注册信号处理函数 sigchld_handler
    // 当子进程结束时，会发送 SIGCHLD 信号，从而调用 sigchld_handler 函数
    signal(SIGCHLD, sigchld_handler);
    // 创建一个新的子进程
    // fork 函数会返回两次，在父进程中返回子进程的 PID，在子进程中返回 0，出错时返回 -1
    pid = fork();
    // 如果返回值为 0，说明当前代码在子进程中
    if (pid == 0)
        // 子进程调用 abort 函数，引发异常终止
        abort();
    // 如果返回值大于 0，说明当前代码在父进程中
    else if (pid > 0) {
        // 父进程睡眠 2 秒，确保有足够时间处理子进程的终止信号
        sleep(2);
        // 输出父进程信息
        printf("parent process\n");
    }
    // 如果返回值小于 0，说明 fork 函数调用出错，直接退出程序
    else
        exit(0);
}